﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace FastSafeDeployM8.Classes
{
    public static class FileExplorerUtils
    {
        public const byte FILE_IMAGE_SMALL_INDEX = 0;
        public const byte FOLDER_IMAGE_SMALL_INDEX = 3;
        public const byte SERVER_IMAGE_SMALL_INDEX = 6;
        public const byte DRIVE_IMAGE_SMALL_INDEX = 9;
        public const string LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        public static string[] SEPARATOR = new string[] { " | " };

        public static void loadTreeDrives(TreeView treeView)
        {
            foreach (Char driveLetter in LETTERS)
            {
                DirectoryInfo directory = new DirectoryInfo(driveLetter + @":\");
                if (directory.Exists)
                {
                    TreeNode node = treeView.Nodes[0].Nodes.Add(directory.Name, directory.Name);
                    node.ImageIndex = node.SelectedImageIndex = DRIVE_IMAGE_SMALL_INDEX;
                    //in order to force the "+" expansion button, add a fake initial node that will be deleted later
                    node.Nodes.Add(new TreeNode("fake"));
                }
            }
        }

        public static void expandTreeNode(TreeNode treeNode)
        {
            treeNode.Nodes.Clear();

            string strPath = getNodePath(treeNode);

            int intNodeIndex = treeNode.Index;

            //MessageBox.Show(strPath);
            if (strPath.Length > 0)
            {
                DirectoryInfo directoryInfo = new DirectoryInfo(@"" + strPath);
                if (directoryInfo.Exists)
                {
                    try
                    {
                        //Getting current node's inner folders
                        DirectoryInfo[] arrDirectories = directoryInfo.GetDirectories();
                        if (arrDirectories.Length > 0)
                        {
                            foreach (DirectoryInfo directory in arrDirectories)
                            {
                                TreeNode node = treeNode.Nodes.Add(directory.Name, directory.Name);
                                node.ImageIndex = node.SelectedImageIndex = FOLDER_IMAGE_SMALL_INDEX;
                                
                                //in order to force the "+" expansion button, add a fake initial node that will be deleted later
                                node.Nodes.Add(new TreeNode("fake"));

                                //getting file from loaded directories - not necessary
                                //FileInfo[] arrFiles = directory.GetFiles();
                                //foreach (FileInfo file in arrFiles)
                                //{
                                //    if (file.Exists)
                                //    {
                                //        TreeNode nodes = treeNode.Nodes[node.Index].Nodes.Add(file.Name);
                                //        nodes.ImageIndex = FILE_IMAGE_SMALL_INDEX;
                                //    }
                                //}
                            }
                        }

                        //Getting current node's inner files
                        FileInfo[] arrFiles = directoryInfo.GetFiles();
                        foreach (FileInfo file in arrFiles)
                        {
                            if (file.Exists)
                            {
                                TreeNode nodes = treeNode.Nodes.Add(file.Name, file.Name);
                                nodes.ImageIndex = FILE_IMAGE_SMALL_INDEX;
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                    }
                }
            }
        }

        public static string getNodePath(TreeNode treeNode)
        {
            string strPath = "";
            TreeNode parent = treeNode;
            while (parent.Level != 0)
            {
                strPath = parent.Name + (parent.Level > 1 ? "\\" : "") + strPath;
                parent = parent.Parent;
            }
            return strPath;
        }

        public static void reloadTreeFromPath(TreeView treeView, string strPath)
        {
            try
            {
                //collapse all nodes.
                treeView.CollapseAll();
                //expand the root Server node to give access to Drives
                TreeNode currentTreeNode = treeView.Nodes[0];
                currentTreeNode.Expand();

                string[] arrTokens = strPath.Split('\\');
                foreach (string strFolder in arrTokens)
                {
                    if (strFolder == "") continue;
                    //MessageBox.Show(strFolder.ToString());
                    string strNodeName = strFolder.Contains(':') ? strFolder + "\\" : strFolder;
                    currentTreeNode = currentTreeNode.Nodes[strNodeName];
                    currentTreeNode.Expand();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Invalid path", "Invalid path", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                //MessageBox.Show(ex.Message);
                //supress wrong paths given inside the editable text path.
            }
        }

        public static void executeQueueOperations(ListBox lbQueue)
        {
            foreach (string strCommand in lbQueue.Items)
            {
                if (strCommand.Length > 0)
                {
                    string[] arrTokens = strCommand.Split(SEPARATOR, StringSplitOptions.None);
                    if (arrTokens.Length==3)
                    {
                        string strOperation = arrTokens[0];
                        string strSourcePath = arrTokens[1];
                        string strTargetPath = arrTokens[2];

                        copyOperation(strSourcePath, strTargetPath);
                    }
                }
            }
        }

        public static void copyOperation(string strSourcePath, string strTargetPath)
        {
            if (strSourcePath[strSourcePath.Length - 1] == '\\') strSourcePath = strSourcePath.Substring(0, strSourcePath.Length - 1);
            if (strTargetPath[strTargetPath.Length - 1] == '\\') strTargetPath = strTargetPath.Substring(0, strTargetPath.Length - 1);
            
            FileInfo fileInfoSource = new FileInfo(strSourcePath);
            FileInfo fileInfoTarget = new FileInfo(strTargetPath);

            DirectoryInfo dirInfoSource = new DirectoryInfo(strSourcePath);
            DirectoryInfo dirInfoTarget = new DirectoryInfo(strTargetPath);

            string cases = (fileInfoSource.Exists ? "1" : "0") + (fileInfoTarget.Exists ? "1" : "0") + (dirInfoSource.Exists ? "1" : "0") + (dirInfoTarget.Exists ? "1" : "0");
            switch (cases)
            {
                case "0000" :
                    MessageBox.Show("X-No file, no directory");
                    break;
                case "0001":
                    MessageBox.Show("X-Only Target Directory exists");
                    break;

                case "0010":
                    MessageBox.Show("Only Source Directory exists");
                    break;
                case "0011":
                    MessageBox.Show("Both Source and Target Directories exists");
                    if (dirInfoSource.Name == dirInfoTarget.Name)
                    {
                        DirectoryCopy(dirInfoSource.FullName, dirInfoTarget.FullName, true, @"F:\MyProjects\FastSafeDeployM8\FastSafeDeployM8\TEST\Packages\Bkp");
                    }
                    break;

                case "0100":
                    MessageBox.Show("X-Only File Target exists");
                    break;

                case "0101":
                    MessageBox.Show("File Target and Directory Target exists");
                    break;
                case "0110":
                    MessageBox.Show("File Target and Directory Source exists");
                    break;

                case "0111":
                    MessageBox.Show("X-File Target and Directory Target and Directory Source exists");
                    break;
                case "1000":
                    MessageBox.Show("X-File Source exists");
                    break;

                case "1001":
                    MessageBox.Show("File Source and Directory Target exists");
                    break;
                case "1010":
                    MessageBox.Show("File Source and Directory Source exists");
                    break;

                case "1011":
                    MessageBox.Show("X-File Source and Directory Source and Directory Target exists");
                    break;

                case "1100":
                    MessageBox.Show("File Source and File Target exists");
                    if (fileInfoSource.Name == fileInfoTarget.Name) 
                    {
                        File.Copy(fileInfoSource.FullName, fileInfoTarget.FullName, true);
                    }
                    break;

                case "1101":
                    MessageBox.Show("X-File Source and File Target and Directory Target exists");
                    break;
                case "1110":
                    MessageBox.Show("X-File Source and File Target and Directory Source exists");
                    break;
                case "1111":
                    MessageBox.Show("X-All exists!");
                    break;

            }

        }

        private static void DirectoryCopy(string sourceDirName, string destDirName, bool copySubDirs, string backupDirName)
        {
            // Get the subdirectories for the specified directory.
            DirectoryInfo dir = new DirectoryInfo(sourceDirName);
            DirectoryInfo[] dirs = dir.GetDirectories();

            if (!dir.Exists)
            {
                throw new DirectoryNotFoundException(
                    "Source directory does not exist or could not be found: "
                    + sourceDirName);
            }

            // If the destination directory doesn't exist, create it. 
            if (!Directory.Exists(destDirName))
            {
                Directory.CreateDirectory(destDirName);
            }

            // Get the files in the directory and copy them to the new location.
            FileInfo[] files = dir.GetFiles();
            foreach (FileInfo file in files)
            {
                string temppath = Path.Combine(destDirName, file.Name);

                FileInfo fileInfo = new FileInfo(temppath);
                bool overwrite = fileInfo.Exists;
                if (overwrite) //do backup first
                {
                    fileInfo.CopyTo(Path.Combine(backupDirName, file.Name), true);
                }
                file.CopyTo(temppath, overwrite);
            }

            // If copying subdirectories, copy them and their contents to new location. 
            if (copySubDirs)
            {
                foreach (DirectoryInfo subdir in dirs)
                {
                    string temppath = Path.Combine(destDirName, subdir.Name);
                    DirectoryCopy(subdir.FullName, temppath, copySubDirs, backupDirName);
                }
            }
        }
    }
}
